package com.baizhi.test;

import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.config.IniSecurityManagerFactory;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.subject.Subject;
import org.junit.Test;

public class ShiroDemoTest2 {
    /*shiro权限管理  框架的认证模块练习
    这里没有连数据库  使用的是shiro.ini配置文件中的模拟数据进行验证
    * */
    //首先，准备两个变量  保存用户页面输入的数据（要验证的身份信息）
//    private String username="li4";
//    private String password="123456";  测试下这两个属性名不叫username和password试试
    private String account="zhang3";
    private String pwd="123456";

    @Test
    public void test(){
        //1、利用安全管理器工厂读取配置文件
        IniSecurityManagerFactory iniSecurityManagerFactory = new IniSecurityManagerFactory("classpath:shiro.ini");
        //2、根据安全管理器工厂对象  获取安全管理器对象
        SecurityManager securityManager = iniSecurityManagerFactory.getInstance();
        //3、利用SecurityUtils工具类 将安全管理器对象和Subject主体建立联系
        SecurityUtils.setSecurityManager(securityManager);
        //4、利用SecurityUtils工具类  获取Subject对象
        Subject subject = SecurityUtils.getSubject();
        //5、将用户的身份信息保存到token（令牌）对象中   账户密码验证对应的令牌对象是UsernamePasswordToken
        UsernamePasswordToken token = new UsernamePasswordToken(account, pwd);
        //6、调用shiro框架提供的subject对象的认证登陆方法login（xxx）
        // 参数是：token令牌对象  无返回值  无异常就说明认证成功  否则认证失败
        try {
            subject.login(token);
            System.out.println("认证成功");
        } catch (AuthenticationException e) {
            e.printStackTrace();
            System.out.println("认证失败");
        }
    }

    /*
    * shiro的认证和授权
    * */
    @Test
    public void test2(){
//        一、先认证
        /*
        * 这里是从配置文件查询数据进行认证授权的
        * shiro.ini配置文件中配置了：
        * 用户的数据和角色权限的信息
        * */
        //1、创建安全管理器工厂 读取配置文件  参数就是：配置文件的路径
        IniSecurityManagerFactory factory = new IniSecurityManagerFactory("classpath:shiro.ini");
        //2、通过工厂获取安全管理器对象
        SecurityManager securityManager = factory.getInstance();
        //3、将安全管理器赋值给工具类SecuirtyUtils （是为了与主体subject建立联系）
        SecurityUtils.setSecurityManager(securityManager);
        //4、通过SecurityUtils工具类  或者shiro的主体对象subject
        Subject subject = SecurityUtils.getSubject();
        //5、封装用户输入的账号 密码到token（令牌对象）  token是shiro的认证方法的参数
        UsernamePasswordToken token = new UsernamePasswordToken(account, pwd);
        //6、认证   调用主体的login方法
        try {
            subject.login(token);
            System.out.println("没有出现异常，说明认证成功");
        } catch (AuthenticationException e) {
            e.printStackTrace();
            /*
            * 认证失败，会出现以下几种异常：
            * 1、UnknownAccountException  没发现账号异常  说明用户传递的账号不存在
            * 2、IncorrectCredentialsException  密码不匹配异常  说明用户传递的密码不正确
            * */
            System.out.println("出现异常，认证失败");
        }
//        二、再授权
        /*
        * 只有认证成功了才允许授权
        * 授权：访问控制  控制谁有权利 访问哪些资源
        * 授权的三大概念： 资源（要访问的内容 项目中体现为数据（即库表））
        *                   权限（能干什么 即能对资源进行哪些操作  项目中体现为业务方法）
        *                   角色（一组权限的集合  这个集合的名字就是角色  将角色赋给谁 谁就拥有该角色下的权限）
        * */
        //1、验证当前主体（即当前操作对象）的认证状态  看起是否成功认证了
        /*
        * subject.isAuthenticated();返回值是boolean类型  只有返回ture才说明认证成功  才能去授权
        * */
        boolean authenticated = subject.isAuthenticated();
        //2、在当前主体认证成功的情况下去给其授权（今天这里采用代码授权）
        if(authenticated){
            /*
            * 代码授权：通过调用方法验证主体有没有权限 或有没有某个角色  来进行流程控制
            * 1、subject.isPermitted("user:delete"); 该方法是判断当前主体是否有某个权限
            *            isPermitted（）的参数：权限字符串
            *            isPermitted（）的返回值：为true时，说明拥有该权限，可以进行相应操作
            * 2、subject.hasRole("vip1"); 该方法是判断当前主体是否拥有某个角色的
            *           hasRole("vip1")的参数是：角色的名字
            *           hasRole("vip1")的返回值： 为true时 说明当前主体有这个角色 拥有该角色下的所有权限
            * */
            //2.1判断当前主体是否有某个权限
            boolean permitted = subject.isPermitted("user:delete");
            if(permitted){
                //若进入该if代码块  说明拥有对用户的删除权限  可以进行用户删除操作
                System.out.println("当前主体拥有删除用户的权限");
            }
            //2.2
            boolean vip1 = subject.hasRole("vip1");
            if(vip1){
                //若进入了该if代码块 说明当前主体由于vip1这个角色  拥有vip1角色下所有权限 能进行相应的操作
                System.out.println("当前主体的拥有vip1这个角色");
            }
        }
    }
}
